package bundle.osgi.remotecontroller;

import bundle.osgi.bridge.inter.Bridge.BRIDGE_TYPE;
import bundle.osgi.bridge.inter.*;
import bundle.osgi.bridge.inter.SmartObject.SMART_TYPE;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.felix.ipojo.annotations.*;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.ops4j.pax.web.service.WebContainer;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.NamespaceException;
import org.xml.sax.InputSource;

/**
 * @author Cedric Gerard
 *
 */
@Component
@Instantiate
public class Controller extends HttpServlet implements DBNotifySubscribers, BridgeServiceSubscriber, Launcher {

    WebContainer webContainer;
    DBNotifyService dbns;
    SPARQLRequestService srs;
    SmartObject so = new SmartObject("NO SMART DEVICE FOUND", "");
    ArrayList<SmartObject> mediaServerList = new ArrayList<SmartObject>();
    int status = 0;
    boolean player = false;
    String preset = "NO PRESET";
    String volume = "0";
    boolean muteState = false;
    String trackDuration = "0:00:00";
    int currentPosition = 0;
    String title = "Empty";
    String rendererStatus = "STOPPED";

    private ConcurrentLinkedQueue<String> update = new ConcurrentLinkedQueue<String>();
    private final Queue<Continuation> continuations = new ConcurrentLinkedQueue<Continuation>();
    private final Thread generator = new Thread("Event generator") {

        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    if (!update.isEmpty()) { //an event has to be send
                        String response = update.poll();
                        System.out.println(response);
                        while (!continuations.isEmpty()) {
                            Continuation continuation = continuations.poll();
                            //get the servlet response
                            HttpServletResponse peer = (HttpServletResponse) continuation.getServletResponse();
                            peer.getWriter().write(response);
                            peer.setStatus(HttpServletResponse.SC_OK);
                            peer.setContentType("text/html");
                            //close the continuation
                            continuation.complete();
                        }
                        //the event has been sent
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e.getMessage(), e);
                }
            }
        }
    };

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("GET received");
        PrintWriter out = resp.getWriter();
        resp.setContentType("text/html");
        out.write(writeIndex());
        out.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        if (!req.getParameterMap().isEmpty()) {
            DEBUG("UPDATE");
//        //test des la création de pièces
//        HashMap<String, String> prop = new HashMap<String, String>();
//        prop.put("X", "30");
//        prop.put("Y", "45");
//        prop.put("Color", "Red");
//        prop.put("Width", "852");
//        prop.put("Height", "852");
//        try {
//            srs.addInstance("Chambre", "Room", prop);
//        } catch (Exception ex) {
//            Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
//        }
//        //fin test
            String id = req.getParameter("device");
            String bridge = req.getParameter("bridge");
            String action = req.getParameter("action");
            if (action != null) {
                if (action.equalsIgnoreCase("on_off")) {
                    DEBUG("ON_OFF");
                    String value = req.getParameter("value");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    DEBUG("id: " + id);
                    DEBUG("brg: " + bridge);
                    DEBUG("val: " + value);
                    //Get the prototype implementation in RDF base with
                    //  -action
                    //  -device type
                    //  -bridge type
                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.DIMMING_LIGHT.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_ON_OFF>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3].substring(0, split[3].length() - 1));
                                DEBUG("valeur: " + value);
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3].substring(0, split[3].length() - 1), value);
                            }
                        }
                    }
                } else if (action.equalsIgnoreCase("set_mute")) {
                    DEBUG("SET_MUTE");
                    String value = req.getParameter("value");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_SET_MUTE>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4] + "/"
                                        + split[5].substring(0, split[5].length() - 1));
                                DEBUG("valeur: " + value);
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3] + "/" + split[4] + "/"
                                        + split[5].substring(0, split[5].length() - 1), "0" + "/" + "Master" + "/" + value);
                            }
                        }
                    }
                } else if (action.equalsIgnoreCase("set_volume")) {
                    DEBUG("SET_VOLUME");
                    String value = req.getParameter("value");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    System.out.println("id: " + id);
                    System.out.println("brg: " + bridge);
                    System.out.println("val: " + value);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_SET_VOLUME>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4] + "/"
                                        + split[5].substring(0, split[5].length() - 1));
                                DEBUG("valeur: " + value);
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3] + "/" + split[4] + "/"
                                        + split[5].substring(0, split[5].length() - 1), "0" + "/" + "Master" + "/" + value);
                            }
                        }
                    }
                } else if (action.equalsIgnoreCase("set_preset")) {
                    DEBUG("SET_PRESET");
                    String value = req.getParameter("value");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_SELECT_PRESET>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4].substring(0, split[4].length() - 1));
                                DEBUG("valeur: " + value);
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3] + "/" + split[4].substring(0, split[4].length() - 1), "0/" + value);
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("previous")) {
                    DEBUG("PREVIOUS");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_PREVIOUS>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3].substring(0, split[3].length() - 1));
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3].substring(0, split[3].length() - 1), "0");
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("play")) {
                    DEBUG("PLAY");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_PLAY>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4].substring(0, split[4].length() - 1));
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3] + "/" + split[4].substring(0, split[4].length() - 1), "0/1");
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("stop")) {
                    DEBUG("STOP");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_STOP>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3].substring(0, split[3].length() - 1));
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3].substring(0, split[3].length() - 1), "0");
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("pause")) {
                    DEBUG("PAUSE");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_PAUSE>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3].substring(0, split[3].length() - 1));
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3].substring(0, split[3].length() - 1), "0");
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("next")) {
                    DEBUG("NEXT");
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_NEXT>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3].substring(0, split[3].length() - 1));
                                ///debug
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3].substring(0, split[3].length() - 1), "0");
                            }
                        }
                    }

                } else if (action.equalsIgnoreCase("seek")) {
                    DEBUG("SEEK");
                    String pourcentage = req.getParameter("value");
                    Float valueOf = Float.valueOf(pourcentage);
                    
                    String[] split_duration = trackDuration.split(":");
                    int sbh = Integer.valueOf(split_duration[0])*3600;
                    int sbm = Integer.valueOf(split_duration[1])*60;
                    int duration = sbh + sbm + Integer.valueOf(split_duration[2]);
                    int value = valueOf.intValue()*duration/100;
                    
                    Bridge bridgeInst = dbns.getBridge(bridge);

                    if (srs != null) {
                        String type = "SELECT ?type WHERE { <http://2012/smart-home#" + id + ">"
                                + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                        String res = srs.sendQuery(type);
                        String[] split = res.split("/");
                        String obj_type = split[2].substring(0, split[2].length() - 1);
                        BRIDGE_TYPE bridge_type = bridgeInst.getType();
                        if (bridge_type == BRIDGE_TYPE.UPNP) {
                            if (obj_type.equals(SMART_TYPE.MEDIA_RENDERER.toString())) {
                                String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_SEEK>"
                                        + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                res = srs.sendQuery(query);
                                split = res.split("/");
                                //debug
                                DEBUG("id: " + id);
                                DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4] + "/" + split[5].substring(0, split[5].length() - 1));
                                ///debug
                                String h, m, s;
                                h = String.valueOf(value / 3600);
                                m = String.valueOf((value % 3600) / 60);
                                s = String.valueOf((value % 3600) % 60);
                                bridgeInst.triggerAction(id, split[2] + "/" + split[3] + "/" + split[4] + "/" + split[5].substring(0, split[5].length() - 1), "0/REL_TIME/" + h + ":" + m + ":" + s);
                            }
                        }
                    }
                    currentPosition = value;

                } else if (action.equalsIgnoreCase("select_server")) {
                    DEBUG("SELECT_SERVER");
                    String value = req.getParameter("value");
                    Iterator<SmartObject> iterator = mediaServerList.iterator();
                    SmartObject next;
                    while (iterator.hasNext()) {
                        next = iterator.next();
                        if (next.getUID().equalsIgnoreCase(value)) {
                            so = next;
                            Bridge bridgeInst = dbns.getBridge(next.getBridgeID());
                            if (srs != null) {
                                String type = "SELECT ?type WHERE { <http://2012/smart-home#" + next.getUID() + ">"
                                        + "<http://2012/smart-home/relation#DEVICE_TYPE> ?type . }";
                                String res = srs.sendQuery(type);
                                String[] split = res.split("/");
                                String obj_type = split[2].substring(0, split[2].length() - 1);
                                BRIDGE_TYPE bridge_type = bridgeInst.getType();
                                if (bridge_type == BRIDGE_TYPE.UPNP) {
                                    if (obj_type.equals(SMART_TYPE.MEDIA_SERVER.toString())) {
                                        String query = "SELECT ?trans WHERE { <http://2012/smart-home/prototype#UPnP_BROWSE>"
                                                + "<http://2012/smart-home/relation#TRANSLATION> ?trans . }";
                                        res = srs.sendQuery(query);
                                        split = res.split("/");
                                        //debug
                                        DEBUG("id: " + next.getUID());
                                        DEBUG("fonction/param: " + split[2] + "/" + split[3] + "/" + split[4] + "/" + split[5] + "/" + split[6] + "/" + split[7] + "/" + split[8] + "/" + split[9] + "/" + split[10] + "/" + split[11].substring(0, split[11].length() - 1));
                                        ///debug
                                        bridgeInst.triggerAction(next.getUID(), split[2] + "/" + split[3] + "/" + split[4] + "/" + split[5] + "/" + split[6] + "/" + split[7] + "/" + split[8] + "/" + split[9] + "/" + split[10] + "/" + split[11].substring(0, split[11].length() - 1), "0/BrowseDirectChildren/0/0", this);
                                    }
                                }
                            }
                            break;
                        }
                    }
                }
            }
        } else {
            DEBUG("CONTINUATION");
            //save the continuation to get the servlet response
            Continuation continuation = ContinuationSupport.getContinuation(req);
            // optionally set a timeout to avoid suspending requests for too long
            continuation.setTimeout(0);
            continuation.suspend();
            continuations.offer(continuation);
        }
    }

    public void callBack(HashMap<String, String> info) {
        DEBUG("CallBack called");
        Iterator<String> iterator = info.keySet().iterator();
        while (iterator.hasNext()) {
            String param = iterator.next();
            DEBUG(param + " = " + info.get(param));
            if (param.contentEquals("CurrentPresetNameList")) {
                DEBUG("preset: " + param);
                preset = info.get(param);
            }
        }
    }

    @Validate
    public void start() {

        if (webContainer != null) {
            try {
                // create a default context to share between registrations
                final HttpContext httpContext = webContainer.createDefaultHttpContext();
                // register the hello world servlet
                final Dictionary initParams = new Hashtable();
                initParams.put("from", "HttpService");
                webContainer.registerServlet("/", this, initParams, httpContext);
                webContainer.registerResources("/html", "/", httpContext);
                DEBUG("HTTP Web controler started");
            } catch (ServletException ex) {
                Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NamespaceException ex) {
                Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
            }
            //register the controller bundle to the data base updates
            if (dbns != null) {
                dbns.subscribe(this);
            }
            generator.start();
        } else {
            DEBUG("ERROR: no compatible HTTP server found");
        }
    }

    @Invalidate
    public void stop() {
        DEBUG("HTTP Controller stopping...");
        if (webContainer != null) {
            webContainer.unregisterServlet(this);
            webContainer = null;
            dbns.unsubscribe(this);
            dbns = null;
            srs = null;
            generator.interrupt();
        }
        DEBUG("HTTP Controller stopped.");
    }

    @Bind
    public void bindWebServer(WebContainer webContainer) {
        this.webContainer = webContainer;
        DEBUG("WebContainer services subscribe");
    }

    @Unbind
    public void unbindWebServer(WebContainer webContainer) {
        this.webContainer = null;
        DEBUG("WebContainer services unsubscribe");
    }

    @Bind
    public void bindDBNotifyService(DBNotifyService dbns) {
        this.dbns = dbns;
        DEBUG("RDF data base notify services subscribe");
    }

    @Unbind
    public void unbindDBNotifyService(DBNotifyService dbns) {
        this.dbns = null;
        DEBUG("RDF data base notify services unsubscribe");
    }

    @Bind
    public void bindSPARQLRequestService(SPARQLRequestService srs) {
        this.srs = srs;
        DEBUG("RDF data base request service subscribe");
    }

    @Unbind
    public void unbindSPARQLRequestService(SPARQLRequestService srs) {
        this.srs = null;
        DEBUG("RDF data base request service unsubscribe");
    }

    public void smartObjectAdded(SmartObject so) {
        DEBUG("new smart object notify received");
        if (so.getType().equals(SMART_TYPE.DIMMING_LIGHT)) {
            this.so = so;
            String service = "SELECT ?serv WHERE { <http://2012/smart-home/prototype#UPnP_ON_OFF>"
                    + "<http://2012/smart-home/relation#SERVICE_ID> ?serv . }";
            String res = srs.sendQuery(service);
            String[] split = res.split("/");
            Bridge bridge = dbns.getBridge(so.getBridgeID());
            if (bridge.newServiceSubscribe(this, so.getUID(), split[2].substring(0, split[2].length() - 1))) {
                DEBUG("follow " + so.getUID() + " status.");
            }

        } else if (so.getType().equals(SMART_TYPE.MEDIA_RENDERER)) {
            this.so = so;
            String service = "SELECT ?serv WHERE { <http://2012/smart-home/prototype#UPnP_SET_MUTE>"
                    + "<http://2012/smart-home/relation#SERVICE_ID> ?serv . }";
            String res = srs.sendQuery(service);
            String[] split = res.split("/");
            Bridge bridge = dbns.getBridge(so.getBridgeID());
            System.out.println("uid: " + so.getUID() + " sid: " + split[2].substring(0, split[2].length() - 1));
            if (bridge.newServiceSubscribe(this, so.getUID(), split[2].substring(0, split[2].length() - 1))) {
                DEBUG("follow " + so.getUID() + " lastChange.");
                player = false;
            }

            service = "SELECT ?serv WHERE { <http://2012/smart-home/prototype#UPnP_PLAY>"
                    + "<http://2012/smart-home/relation#SERVICE_ID> ?serv . }";
            res = srs.sendQuery(service);
            split = res.split("/");
            System.out.println("uid: " + so.getUID() + " sid: " + split[2].substring(0, split[2].length() - 1));
            if (bridge.newServiceSubscribe(this, so.getUID(), split[2].substring(0, split[2].length() - 1))) {
                DEBUG("follow " + so.getUID() + " lastChange.");
                player = true;
            }

            //Get presets list
            String actions = "ListPresets";
            actions += "/InstanceID/CurrentPresetNameList";
            String params = "0";
            bridge.triggerAction(so.getUID(), actions, params, this);

        } else if (so.getType().equals(SMART_TYPE.MEDIA_SERVER)) {
            this.so = so;
            mediaServerList.add(so);
        }
        update.offer("AddDevice/" + so.getUID());
    }

    public void smartObjectRemoved(SmartObject so) {
        DEBUG("leaving smart object notify received");
        if (this.so.getUID().contentEquals(so.getUID())) {
            if (so.getType() == SMART_TYPE.MEDIA_SERVER) {
                mediaServerList.remove(so);
            }
            this.so = new SmartObject("NO DIMMING LIGHT FOUND", "");
            update.offer("RemoveDevice/" + so.getUID());
        }
    }

    public void smartObjectUpdated(SmartObject so) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void serviceNotify(String UDN, String device, String variable, String value) {
        if (variable.equalsIgnoreCase("status")) {
            //DEBUG("new value: " + value);
            status = Integer.valueOf(value);
            update.offer("device/" + UDN + "/var/status/value/" + status);
        } else if (variable.equalsIgnoreCase("LastChange")) {
            DEBUG("variable: " + variable);
            String offer = "device/" + UDN + "/var/LastChange/";
            SAXBuilder sxb = new SAXBuilder();
            try {
                Document document = sxb.build(new InputSource(new StringReader(value)));
                Element root = document.getRootElement();
                List<Element> children = root.getChildren();
                Iterator<Element> iterator = children.iterator();
                while (iterator.hasNext()) { //for each instanceID
                    Element current = iterator.next();
                    DEBUG("IntanceID " + current.getAttributeValue("val"));
                    List<Element> childList = current.getChildren();
                    Iterator<Element> iterChild = childList.iterator();
                    Element child;
                    while (iterChild.hasNext()) {
                        child = iterChild.next();
                        String attributeValue = child.getAttributeValue("val");
                        DEBUG(attributeValue);
                        if (child.getName().equalsIgnoreCase("Volume")) {
                            if (child.getAttributeValue("channel").equalsIgnoreCase("Master")) {
                                volume = attributeValue;
                                update.offer(offer+"vol/"+volume);
                            }
                        } else if (child.getName().equalsIgnoreCase("Mute")) {
                            muteState = Boolean.valueOf(attributeValue);
                            update.offer(offer+"mute/"+muteState);
                        } else if (child.getName().equalsIgnoreCase("PresetName")) {
                            preset = attributeValue;
                            update.offer(offer+"preset/"+preset);
                        } else if (child.getName().equalsIgnoreCase("CurrentTrackDuration")) {
                            trackDuration = attributeValue;
                            update.offer(offer+"duration/"+trackDuration);
                        } else if (child.getName().equalsIgnoreCase("AVTransportURI")) {
                            String[] split = attributeValue.split("/");
                            title = split[split.length - 1];
                            update.offer(offer+"title/"+title);
                        } else if (child.getName().equalsIgnoreCase("TransportState")) {
                            rendererStatus = attributeValue;
                            if (attributeValue.contentEquals("STOPPED")) {
                                currentPosition = 0;
                                update.offer(offer+"state/STOPPED");
                            } else if (attributeValue.contentEquals("PAUSED_PLAYBACK")) {
                                update.offer(offer+"state/PAUSED");
                            } else if (attributeValue.contentEquals("PLAYING")) {
                                update.offer(offer+"state/PLAYING");
                            }
                        }
                    }
                }
            } catch (JDOMException ex) {
                Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public String writeIndex() {

        String xmlPage = "<!DOCTYPE html>"
                + "<html>"
                + "<head>"
                + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
                + "<link rel=\"stylesheet\" href=\"html/style.css\">"
                + "<title>Device Controler</title>"
                + "<script language=\"JavaScript\" type=\"text/javascript\" src=\"html/jquery-1.7.2.js\"></script>"
                + "<script language=\"JavaScript\" type=\"text/javascript\"  src=\"html/action.js\"></script>"
                + "</head>"
                + "<body>"
                + "<div id=\"deviceInfo\">"
                + "<h3>Device info</h3>"
                + "<p>UID: </p><p id=\"uid\">" + so.getUID() + "</p>"
                + "<p>Name:</p><p id=\"name\">" + so.getName() + "</p>"
                + "<p>Bridge: </p><p id=\"bridge\">" + so.getBridgeID() + "</p>"
                + "<p>Type: </p><p id=\"type\">" + so.getType() + "</p>"
                + "</div>";

        if (so.getType().equals(SMART_TYPE.DIMMING_LIGHT)) {
            xmlPage += "<div id=\"deviceCmd\">" + writeDimmingLight(status) + "</div>";
        } else if (so.getType().equals(SMART_TYPE.MEDIA_RENDERER)) {
            if (player) {
                xmlPage += "<div id=\"deviceCmd\">" + writeRenderer() + "</div>";
            } else {
                xmlPage += "<div id=\"deviceCmd\">" + writeMinRenderer() + "</div>";
            }
        } else if (so.getType().equals(SMART_TYPE.MEDIA_SERVER)) {
            xmlPage += "<div id=\"deviceCmd\">" + writeServer() + "</div>";
        }
        xmlPage += "</body> </html>";
        return xmlPage;
    }

    public String writeDimmingLight(int val) {
        boolean state = (val == 1);
        if (state) {
            return "<div id=\"remoteGUI\">"
                    + "<h3>Remote dimming light controler</h3>"
                    + "<img src=\"html/lightON.png\"  alt=\"Light is ON\" id=\"light\"/>"
                    + "<button onClick=\"on_off('" + so.getUID() + "','" + so.getBridgeID() + "','" + !state + "','ON_OFF');\" id=\"switch\">Switch OFF</button>"
                    + "</div>";
        } else {
            return "<div id=\"remoteGUI\">"
                    + "<h3>Remote dimming light controler</h3>"
                    + "<img src=\"html/lightOFF.png\"  alt=\"Light is OFF\" id=\"light\"/>"
                    + "<button onClick=\"on_off('" + so.getUID() + "','" + so.getBridgeID() + "','" + !state + "','ON_OFF');\" id=\"switch\">Switch ON</button>"
                    + "</div>";
        }

    }

    public String writeMinRenderer() {
        String[] split = preset.split(",");

        String page = "<!DOCTYPE html>"
                + "<html>"
                + "<head>"
                + "<title>Media Renderer controller</title>"
                + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
                + " </head>"
                + "<body>"
                + " <div id=\"remoteGUI\">"
                + " <div id=\"preset\">"
                + " <h3>Preset</h3>"
                + " <select name=\"presets\" onChange=\"changePreset('" + so.getUID() + "','" + so.getBridgeID() + "',this.options[this.selectedIndex].value,'SET_PRESET');\">";
        int i = 0;
        while (i < split.length) {
            page += " <option>" + split[i] + "</option>";
            i++;
        }
        page += "</select>"
                + "</div>"
                + "<div id=\"volume\">"
                + "<h3>Sound</h3>"
                + "<input type=\"range\" min=\"0\" max=\"100\" value=\"" + volume + "\" step=\"1\" name=\"sound\""
                + "oninput=\"volume('" + so.getUID() + "','" + so.getBridgeID() + "'," + "value" + ",'SET_VOLUME')\">"
                + "<button  onClick=\"mute('" + so.getUID() + "','" + so.getBridgeID() + "','" + !muteState + "','SET_MUTE');\" id=\"mute\">mute</button>"
                + "</div>"
                + "</div>"
                + "</body>"
                + "</html>";
        return page;
    }

    public String writeRenderer() {
        String[] split = preset.split(",");

        String page = "<!DOCTYPE html>"
                + "<html>"
                + "<head>"
                + "<title>Media Renderer controller</title>"
                + "<meta name=\"uid\" content=\"" + so.getUID() + "\"/>"
                + "<meta name=\"bridge\" content=\"" + so.getBridgeID() + "\"/>"
                + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
                + "<link href=\"html/lecteurLayout.css\" rel=\"stylesheet\" type=\"text/css\" />"
                + "<link href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css\" rel=\"stylesheet\" type=\"text/css\"/>"
                + "<link rel=\"stylesheet\" href=\"css/jquery.slider.min.css\" type=\"text/css\" charset=\"utf-8\">"
                + "<script src=\"http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js\"></script>"
                + "<script src=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js\"></script>"
                + "</head>"
                + "<body>"
                + " <div id=\"container\">"
                + " <h1> Player </h1>"
                + " <div id=\"title_l\" name=\"title\" >" + title + "</div>"
                + " <table class=\"title_duration\">"
                + "     <tr>";

        String hour = String.valueOf(currentPosition / 3600);
        String min = String.valueOf((currentPosition % 3600) / 60);
        String sec = String.valueOf((currentPosition % 3600) % 60);

        page += "<td id=\"time_l\" name=\"currentTime\">" + hour + ":" + min + ":" + sec + "</td>"
                + "<th> <div id=\"time\"></div> </td>"
                + "<td id=\"duration\" name=\"trackDuration\">" + trackDuration + "</td>"
                + "</tr>"
                + "</table>"
                + "<table class=\"control_table\">"
                + "<tr>"
                + "<td class=\"prec\"><a href=\"#\" onclick=\"press('" + so.getUID() + "','" + so.getBridgeID() + "','PREVIOUS');\"><img  id=\"prec_btn\" src=\"html/prec.png\"/></a></td>"
                + "<td class=\"play\"><a href=\"#\" onclick=\"press('" + so.getUID() + "','" + so.getBridgeID() + "','PLAY');\"><img id=\"play_btn\" src=\"html/play.png\"/></a></td>"
                + "<td class=\"pause\"><a href=\"#\" onclick=\"press('" + so.getUID() + "','" + so.getBridgeID() + "','PAUSE');\"><img id=\"pause_btn\" src=\"html/pause.png\"/></a></td>"
                + "<td class=\"stop\"><a href=\"#\"  onclick=\"press('" + so.getUID() + "','" + so.getBridgeID() + "','STOP');\"><img id=\"stop_btn\" src=\"html/stop.png\"/></a></td>"
                + "<td class=\"suiv\"><a href=\"#\" onclick=\"press('" + so.getUID() + "','" + so.getBridgeID() + "','NEXT');\"><img id=\"suiv_btn\" src=\"html/suiv.png\"/></a></td>"
                + "<td class=\"volume\"><a id=\"mute_cmd\" href=\"#\" onClick=\"mute('" + so.getUID() + "','" + so.getBridgeID() + "','" + !muteState + "','SET_MUTE');\"><img id=\"mute_btn\" src=\"html/volume.png\"/></a></td>"
                + "<th>"
                + "<input id=\"vol_b\" type=\"range\" min=\"0\" max=\"100\" value=\"" + volume + "\"step=\"1\" name=\"sound\"" + "oninput=\"volume('" + so.getUID() + "','" + so.getBridgeID() + "'," + "value" + ",'SET_VOLUME')\">"
                + "</th>"
                + "</tr>"
                + "</table> "
                + "<table style=\"width: 100%\" >"
                + "<tr>"
                + "<th>Preset</th>"
                + "<td><select id=\"presets\" name=\"select\" onChange=\"changePreset('" + so.getUID() + "','" + so.getBridgeID() + "',this.options[this.selectedIndex].value,'SET_PRESET');\">";
        int i = 0;
        while (i < split.length) {
            page += " <option>" + split[i] + "</option>";
            i++;
        }
        page += "</select></td>"
                + "</tr>"
                + "</table>"
                + "</div>"
                + "</body>"
                + "</html>";

        return page;
    }

    public String writeServer() {
        String page = "<!DOCTYPE html>"
                + "<html>"
                + "<head>"
                + "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">"
                + "<title>Media server</title>"
                + "</head>"
                + "<body>"
                + "<div id=\"server\">"
                + "<h3>Files</h3>"
                + "<select name=\"servers\" onChange=\"changeServer(this.options[this.selectedIndex].value,'SELECT_SERVER');\">";
        Iterator<SmartObject> iterator = mediaServerList.iterator();
        while (iterator.hasNext()) {
            SmartObject next = iterator.next();
            page += "<option>" + next.getUID() + "</option>";
        }
        page += "</select>"
                + "<select name=\"file\" size=\"10\">"
                + "<option>File1</option>"
                + "<option>File2</option>"
                + "<option>File3</option>"
                + "</select>"
                + "</div>"
                + "</body>"
                + "</html>";
        return page;
    }
    private static final long serialVersionUID = -7578840142400570555L;

    //*******************************
    //Debug functions
    //Todo adding trace file with
    //2 degree of debug	
    //*******************************
    public static boolean DEBUG = true; 	    //debug status

    private static void DEBUG(String debug) {
        if (Controller.DEBUG) {
            System.out.println("Web Controler:[" + new Date().getTime() + "]   " + debug);
        }
    }
}
